﻿using Engine.Material.Deferred;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using PloobsEngine;
using PloobsEngine.Cameras;
using PloobsEngine.Commands;
using PloobsEngine.Features;
using PloobsEngine.Input;
using PloobsEngine.Light;
using PloobsEngine.Loader;
using PloobsEngine.Material;
using PloobsEngine.Modelo;
using PloobsEngine.Physics;
using PloobsEngine.Physics.Bepu;
using PloobsEngine.SceneControl;
using PloobsEngineDemo3;

namespace Etapa1.Screens
{
    /// <summary>
    /// Water Screen
    /// Shows the true water example
    /// </summary>
    public class WaterCompleteScreen : SceneScreen
    {
        private BepuPhysicWorld physicWorld;
        private BrutalForceWorld mundo;
        private EngineStuff engine;        
        ICamera cam;

        public WaterCompleteScreen(EngineStuff es)
        {
            this.engine = es;
            physicWorld = new BepuPhysicWorld();
            mundo = new BrutalForceWorld(physicWorld);                                    
        }
        
        public override void LoadContent(EngineStuff es)
        {            
            InputAdvanced inp = new InputAdvanced(engine);
            engine.AddComponent(inp);

            base.LoadContent(es);            

            #region Models

            ///Load rhe scene from the xml
            ExtractXmlModelLoader me = new ExtractXmlModelLoader();
            ModelLoaderData data = me.Load("shadow");

            foreach (var item in data.ModelMeshesInfo)
            {
                ComposedPartsModel sm = new ComposedPartsModel(item);
                sm.LoadModelo();
                IPhysicObject pi = new TriangleMeshObject(sm, item.pos, Matrix.CreateFromQuaternion(item.ori), item.scale);
                pi.isMotionLess = true;
                CustomDeferred shader = new CustomDeferred(item.HasTexture(TextureType.GLOW), item.HasTexture(TextureType.BUMP), item.HasTexture(TextureType.SPECULAR), item.HasTexture(TextureType.PARALAX));                
                shader.Initialize();
                IMaterial mat = new Material(shader, MaterialType.DEFERRED);
                IObject obj4 = new SimpleObject(mat, pi, sm);
                mundo.AddObject(obj4);
            }

            ///Load Lights
            foreach (var item in data.LightsInfo)
            {
                mundo.AddLight(item);
            }

            
            ///Create the water
            ///Water is just a Shader that Creats a Water like texture and binds it to a model
            {
                IModelo sm = new SimpleModel("..\\Content\\Model\\block");
                sm.LoadModelo();
                Matrix trans = Matrix.CreateTranslation(new Vector3(100,50, 0));
                Plane plano = Plane.Transform(new Plane(0, 1, 0, 0), trans);
                IPhysicObject pi = new BoxObject(new Vector3(1, 1, 1), trans, 1, 100, new Vector3(1300, 0.1f, 1300));
                pi.isMotionLess = true;
                ///Water shader, will refract and reflect according to the plano passed in the parameter
                ///Using default Parameters, there are lots of things that can be changed. See WaterCompleteShader 
                WaterCompleteShader shader = new WaterCompleteShader(800, 600, plano, 0);                
                shader.SpecularIntensity = 0.01f;
                shader.SpecularPower = 50;
                shader.Initialize();
                IMaterial mat = new Material(shader);
                IObject obj4 = new SimpleObject(mat, pi, sm);
                mundo.AddObject(obj4);

            }

            //for (int i = -5 ; i < 5; i++)
            //{
            //    for (int j = -5 ; j < 5; j++)
            //    {
            //        IModelo sm = new SimpleModel("..\\Content\\Model\\block", "..\\Content\\Textures\\blue");
            //        sm.LoadModelo();
            //        GhostObject pi = new GhostObject(new Vector3(i * 150, 50, j * 150), Matrix.Identity, new Vector3(10, 200, 10));
            //        pi.isMotionLess = true;
            //        CustomDeferred shader = new CustomDeferred(false, false, false, false);
            //        shader.Initialize();
            //        IMaterial mat = new Material(shader, MaterialType.DEFERRED);
            //        IObject obj4 = new SimpleObject(mat, pi, sm);
            //        mundo.AddObject(obj4);
            //        PointLight pl = new PointLight(new Vector3(i * 150, 150, j * 150), Color.BlueViolet, 100, 5);
            //        mundo.AddLight(pl);
            //    }

            //}

            

            #endregion            

            cam = new CameraFirstPerson(true);            
            cam.FarPlane = 3000;

            LightThrowBepu lt = new LightThrowBepu(mundo, engine);         
            
            #region NormalLight
            DirectionalLight ld1 = new DirectionalLight(Vector3.Left, Color.White);
            DirectionalLight ld2 = new DirectionalLight(Vector3.Right, Color.White);
            DirectionalLight ld3 = new DirectionalLight(Vector3.Backward, Color.White);
            DirectionalLight ld4 = new DirectionalLight(Vector3.Forward, Color.White);
            DirectionalLight ld5 = new DirectionalLight(Vector3.Down, Color.White);
            float li = 0.4f;
            ld1.LightIntensity = li;
            ld2.LightIntensity = li;
            ld3.LightIntensity = li;
            ld4.LightIntensity = li;
            ld5.LightIntensity = li;
            mundo.AddLight(ld1);
            mundo.AddLight(ld2);
            mundo.AddLight(ld3);
            mundo.AddLight(ld4);
            mundo.AddLight(ld5);
            #endregion
            
            ////Criacao de uma Tecnica
            DeferredRenderTechnic dr = new DeferredRenderTechnic(engine);
            
            IRenderTechnic[] rt = new IRenderTechnic[] { dr };
            dr.isDebug = true;                                
            this.RenderTechnics = rt;            
            mundo.AddCamera(cam);
            this.World = mundo;


            ///Skybox Settings
            Skybox sk = new Skybox(engine);
            engine.AddComponent(sk);

            SkyBoxUpdateParametersCommand su = new SkyBoxUpdateParametersCommand(cam, "..\\Content\\Textures\\grassCUBE");
            CommandProcessor.getCommandProcessor().SendCommandAssyncronous(su);
            
        }
    }
}

